package com.aphrodite.ui.widgets;

import java.util.Vector;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

/**
 * A simple list
 * 
 * @author kentelt
 * 
 */
public class List extends TraversableWidget {
	/* Location to start drawing text from */
	int textStart = 5;
	/* The icons list */
	Vector icons = new Vector();

	/* Pad between the left border of the list and the image */
	final int imagePad = 3;
	/* Height of a single list item */
	int itemHeight;

	/* Number of elements visible */
	private int linesVisible = 1;

	/* String items list */
	Vector list = new Vector();
	/* Number of lines that are visible */
	private int noOfLines;
	/* Current Selected */
	int selIndex;
	Image tmpImage;
	String tmpString;

	/* top element in the list */
	private int topElement;

	/* Total number of items */
	private int total;

	/**
	 * Create a new list
	 * 
	 * @param theme
	 * @param width
	 *            of the list
	 * @param height
	 *            of the list
	 */
	public List(Theme theme, int width, int height) {
		super(theme, width, height);
		updateModel();
	}

	public void addItem(String item, Image icon) {
		list.addElement(item);
		icons.addElement(icon);
		updateModel();
		reDrawWidget();
	}

	// public void removeAllItems() {
	// list.removeAllElements();
	// icons.removeAllElements();
	// updateModel();
	// reDrawWidget();
	// }

	public Image getIcon(int index) {
		return (Image) icons.elementAt(index);
	}

	/**
	 * 
	 * @return current selected index
	 */
	public int getSelectedIndex() {
		return selIndex;
	}

	public String getString(int index) {
		return (String) list.elementAt(index);
	}

	private void makeSelectedVisible() {
		if (selIndex >= 0) {
			if (selIndex < topElement) {
				topElement = selIndex;
			} else if (selIndex - topElement + 1 > linesVisible) {
				topElement = selIndex - linesVisible + 1;
			}
		}
	}

	public boolean moveDown() {
		if (selIndex < total - 1) {
			++selIndex;
			makeSelectedVisible();
			reDrawWidget();
			return true;
		} else {
			// location = LOWER;
			// moveNextFlag++; if (moveNextFlag > 2)
			isInFocus = false;
			return false;

		}

	}

	public boolean moveUp() {
		if (selIndex > 0) {
			--selIndex;
			makeSelectedVisible();
			reDrawWidget();
			return true;
		} else {
			/* create aa delay when losing focus */
			// location = UPPER;
			// moveNextFlag++;
			// if (moveNextFlag > 2)
			isInFocus = false;
			return false;
		}
	}

	public void render(Graphics g) {
		if (!isVisible)
			return;
		capture(g, width, height, true);
		int curr = topElement;
		int last = topElement + noOfLines;
		int listItem_Y = 0;
		boolean isSel;
		for (; curr < total && curr < last;) {
			isSel = (curr == selIndex);
			if (isSel) {
				renderSelector(g, listItem_Y);
			}
			renderItem(g, isSel, curr, listItem_Y);
			listItem_Y += itemHeight;
			++curr;
		}
		release(g, width, height, true);
	}

	/* needs to be overriden. renders the icon and the string item */
	void renderItem(final Graphics g, final boolean isSelected, final int index, final int y) {
		tmpImage = (Image) icons.elementAt(index);
		tmpString = (String) list.elementAt(index);
		if (tmpImage != null) {
			// g.drawImage(tmpImage, imagePad, y + (itemHeight / 2) -
			// tmpImage.getHeight() / 2, 0);
			g.drawImage(tmpImage, imagePad, y + itemHeight / 2, Graphics.VCENTER);

		}
		if (tmpString != null) {
			g.setColor(isSelected ? theme.highLightFGColor : theme.fgColor);
			if (theme.bmFont != null) {
				theme.bmFont.drawString(g, tmpString, textStart, y + itemHeight / 2, Graphics.VCENTER);
			} else {
				g.setFont(theme.widgetFont);
				g.drawString(tmpString, textStart, y, 0);
			}
		}
	}

	/* needs to be overriden */
	void renderSelector(final Graphics g, final int y) {
		g.setColor(theme.highLightColor);
		// g.fillRect(0, y, width + 1, itemHeight);
		g.fillRoundRect(0, y, width, itemHeight, 3, 3);
	}

	/**
	 * compute starting point for the string
	 */
	void computeTextStart() {
		/* icon width+ Right pad */
		textStart = imagePad + getWidestIcon();
	}

	int getWidestIcon() {
		/* set the image-string pad */
		Image icon;
		int widestIcon = 0;
		for (int i = 0; i < icons.size(); i++) {
			icon = (Image) icons.elementAt(i);
			if (icon != null) {
				if (icon.getWidth() > widestIcon)
					widestIcon = icon.getWidth();
			}
		}
		/* Widest icon + icon pad */
		return widestIcon == 0 ? widestIcon + 2 : 0;
	}

	/* needs to be overriden */
	void setItemHeight() {
		itemHeight = theme.bmFont == null ? theme.getWidgetFont().getHeight() : theme.bmFont.getHeight();
		itemHeight++;
	}

	protected boolean traverse(int dir, int viewportWidth, int viewportHeight, int[] visRect_inout) {
		return false;
	}

	protected final void updateModel() {
		setItemHeight();
		noOfLines = height / itemHeight;
		total = list.size();
		selIndex = -1;
		linesVisible = (total > noOfLines) ? noOfLines : total;
		computeTextStart();
		moveDown();
	}

	/**
	 * Resize the list to accomodate all the list items horizontally and
	 * vertically.
	 * <p>
	 * Triggers a stateChanged event
	 * </p>
	 * 
	 * @see StateListener
	 */
	public final void resizeToFit() {
		super.height = itemHeight * list.size();
		/* find the widest string list item */
		int tmpWidth = 0;
		String tmpData = null;
		for (int i = 0; i < list.size(); i++) {
			tmpData = (String) list.elementAt(i);
			if (tmpData != null) {
				int tmp = (theme.bmFont == null) ? theme.widgetFont.stringWidth(tmpData) : theme.bmFont
						.stringWidth(tmpData);
				if (tmp > tmpWidth)
					tmpWidth = tmp;
			}
		}
		/* set the width to the widest string item + right pad (2) */
		super.width = textStart + tmpWidth + 2;
		updateModel();
		stateChanged(this);
	}
}
